#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QString>
#include <QMessageBox>
#include <QPixmap>
#include <QScreen>
#include <QDir>
#include <QRandomGenerator>
#include <QElapsedTimer>

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "psapi.lib")

// 定义截图保存根路径
#define SCREENSHOT_ROOT_PATH "E:\\project_jietu"
// 定义随机截图最小间隔（10分钟 = 600000毫秒）
#define MIN_RANDOM_SCREENSHOT_INTERVAL 600000
// 定义随机截图最大间隔（30分钟 = 1800000毫秒，可按需调整）
#define MAX_RANDOM_SCREENSHOT_INTERVAL 1800000

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_hook(nullptr)
    , m_keyboardHook(nullptr)  // 初始化键盘钩子句柄
    , m_lastHWND(nullptr)
    , m_timeout(30 * 60 * 1000)  // 30分钟超时(毫秒)
    , m_isRunning(false)
    , m_randomScreenshotInterval(0)
    , m_lastRandomScreenshot(0)
{
    ui->setupUi(this);

    // 初始化定时器
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &MainWindow::checkTimeout);

    // 初始化随机截图定时器
    m_randomScreenshotTimer = new QTimer(this);
    connect(m_randomScreenshotTimer, &QTimer::timeout, this, &MainWindow::takeRandomScreenshot);

    // 初始化窗口计时
    m_windowElapsedTimer = new QElapsedTimer();

    // 初始状态设置
    ui->lineEdit_showOk->setText("未运行");
    ui->pushButton_end->setEnabled(false);

    // 创建截图保存目录（若不存在）
    QDir screenshotDir(SCREENSHOT_ROOT_PATH);
    if (!screenshotDir.exists()) {
        if (screenshotDir.mkpath(".")) {
            logInfo(QString("[系统] 截图目录已创建: %1").arg(SCREENSHOT_ROOT_PATH));
        } else {
            QMessageBox::warning(this, "警告",
                                 QString("创建截图目录失败: %1，请检查权限").arg(SCREENSHOT_ROOT_PATH));
        }
    } else {
        logInfo(QString("[系统] 截图目录已存在: %1").arg(SCREENSHOT_ROOT_PATH));
    }
}

MainWindow::~MainWindow()
{
    unsetMouseHook();
    unsetKeyboardHook();  // 析构时移除键盘钩子，避免资源泄露
    delete m_windowElapsedTimer;
    delete ui;
}

// 鼠标钩子回调函数
LRESULT CALLBACK MainWindow::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0 && (wParam == WM_LBUTTONDOWN || wParam == WM_RBUTTONDOWN ||
                       wParam == WM_MOUSEMOVE)) {  // 增加鼠标移动检测
        HWND hWnd = GetForegroundWindow();
        if (hWnd)
        {
            for (QWidget *widget : qApp->topLevelWidgets()) {
                MainWindow *mainWindow = qobject_cast<MainWindow*>(widget);
                if (mainWindow && mainWindow->m_isRunning) {
                    QMetaObject::invokeMethod(mainWindow, "handleWindowChange",
                                              Qt::QueuedConnection,
                                              Q_ARG(HWND, hWnd));
                    break;
                }
            }
        }
    }
    return CallNextHookEx(nullptr, nCode, wParam, lParam);
}

// 键盘钩子回调函数（监听键盘操作触发窗口切换）
LRESULT CALLBACK MainWindow::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    // 监听普通按键按下(WM_KEYDOWN)和系统按键按下(WM_SYSKEYDOWN，如Alt+Tab、Win键等)
    if (nCode >= 0 && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
    {
        HWND hWnd = GetForegroundWindow();  // 获取当前激活的窗口句柄
        if (hWnd)
        {
            // 遍历应用顶级窗口，找到主窗口实例
            for (QWidget *widget : qApp->topLevelWidgets()) {
                MainWindow *mainWindow = qobject_cast<MainWindow*>(widget);
                // 主窗口存在且监控正在运行时，触发窗口切换处理逻辑
                if (mainWindow && mainWindow->m_isRunning) {
                    QMetaObject::invokeMethod(mainWindow, "handleWindowChange",
                                              Qt::QueuedConnection,
                                              Q_ARG(HWND, hWnd));
                    break;
                }
            }
        }
    }
    // 必须传递钩子信息，否则会影响系统正常键盘功能
    return CallNextHookEx(nullptr, nCode, wParam, lParam);
}

// 设置鼠标钩子
bool MainWindow::setMouseHook()
{
    if (m_hook) return true;

    m_hook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(nullptr), 0);
    if (!m_hook)
    {
        QMessageBox::critical(this, "错误",
                              QString("设置鼠标钩子失败，错误码: %1")
                                  .arg(GetLastError()));
        return false;
    }
    return true;
}

// 设置键盘钩子（注册低级键盘钩子，无需注入其他进程）
bool MainWindow::setKeyboardHook()
{
    if (m_keyboardHook) return true;  // 已设置则直接返回成功

    // 注册低级键盘钩子，回调函数为KeyboardProc，全局生效
    m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(nullptr), 0);
    if (!m_keyboardHook)
    {
        QMessageBox::critical(this, "错误",
                              QString("设置键盘钩子失败，错误码: %1")
                                  .arg(GetLastError()));
        return false;
    }
    return true;
}

// 移除鼠标钩子
void MainWindow::unsetMouseHook()
{
    if (m_hook)
    {
        UnhookWindowsHookEx(m_hook);
        m_hook = nullptr;
    }
}

// 移除键盘钩子（释放系统资源）
void MainWindow::unsetKeyboardHook()
{
    if (m_keyboardHook)
    {
        UnhookWindowsHookEx(m_keyboardHook);  // 解除键盘钩子注册
        m_keyboardHook = nullptr;             // 重置句柄为null
    }
}

// 获取窗口标题
QString MainWindow::getWindowTitle(HWND hWnd)
{
    int length = GetWindowTextLength(hWnd);
    if (length == 0) return "无标题";

    QString title;
    title.resize(length + 1);
    GetWindowText(hWnd, (LPWSTR)title.data(), length + 1);
    title.truncate(length);
    return title;
}

// 获取进程名称
QString MainWindow::getProcessName(DWORD processId)
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
    if (!hProcess)
    {
        return "无法获取进程名(权限不足)";
    }

    WCHAR name[MAX_PATH];
    if (GetModuleBaseNameW(hProcess, nullptr, name, MAX_PATH))
    {
        CloseHandle(hProcess);
        return QString::fromWCharArray(name);
    }

    CloseHandle(hProcess);
    return "未知进程名";
}

// 获取进程路径
std::string MainWindow::getProcessPath(HWND hWnd)
{
    if (m_processPathMap.find(hWnd) != m_processPathMap.end())
    {
        return m_processPathMap[hWnd];
    }

    DWORD processId;
    GetWindowThreadProcessId(hWnd, &processId);

    if (m_processNameMap.find(processId) == m_processNameMap.end()) {
        m_processNameMap[processId] = getProcessName(processId);
    }

    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
    if (!hProcess)
    {
        return "无法获取进程信息(权限不足)";
    }

    char path[MAX_PATH];
    if (GetModuleFileNameExA(hProcess, nullptr, path, MAX_PATH))
    {
        CloseHandle(hProcess);
        m_processPathMap[hWnd] = path;
        return path;
    }

    CloseHandle(hProcess);
    return "未知路径";
}

// 处理窗口切换（复用原有逻辑，键盘/鼠标切换统一处理）
void MainWindow::handleWindowChange(HWND newHWND)
{
    if (!m_isRunning) return;

    // 核心修改：用「窗口句柄+场景标识」作为key，确保同一窗口的切换场景仅截图一次
    QString screenshotKey = QString("%1|window_switch").arg((quintptr)newHWND);
    if (m_screenshotRecordMap.find(screenshotKey) == m_screenshotRecordMap.end()) {
        takeScreenshot("window_switch");
        m_screenshotRecordMap[screenshotKey] = true;  // 标记该窗口的切换场景已截图
    }

    if (newHWND != m_lastHWND)
    {
        // 计算上一个窗口的运行时间
        if (m_lastHWND && m_windowElapsedTimer->isValid())
        {
            qint64 duration = m_windowElapsedTimer->elapsed();
            m_totalTimeMap[m_lastHWND] += duration;

            DWORD lastProcessId;
            GetWindowThreadProcessId(m_lastHWND, &lastProcessId);
            QString lastProcessName = m_processNameMap[lastProcessId];
            QString lastWindowTitle = getWindowTitle(m_lastHWND);

            // 转换为分钟和秒显示
            qint64 seconds = duration / 1000;
            qint64 minutes = seconds / 60;
            seconds %= 60;

            qint64 totalSeconds = m_totalTimeMap[m_lastHWND] / 1000;
            qint64 totalMinutes = totalSeconds / 60;
            totalSeconds %= 60;

            QString info = QString("[%1] 窗口切换 - 应用名称: %2 | 窗口标题: %3 | 本次运行: %4分%5秒 | 总运行: %6分%7秒")
                               .arg(QDateTime::currentDateTime().toString("HH:mm:ss"))
                               .arg(lastProcessName)
                               .arg(lastWindowTitle)
                               .arg(minutes).arg(seconds)
                               .arg(totalMinutes).arg(totalSeconds);
            logInfo(info);
        }

        // 更新信息并开始计时
        m_lastHWND = newHWND;
        m_windowElapsedTimer->restart();  // 使用高分辨率计时器
        updateTimeout();

        // 获取新窗口信息
        DWORD newProcessId;
        GetWindowThreadProcessId(newHWND, &newProcessId);
        QString newProcessName = getProcessName(newProcessId);
        QString newWindowTitle = getWindowTitle(newHWND);

        QString newInfo = QString("[%1] 新窗口激活 - 应用名称: %2 | 窗口标题: %3")
                              .arg(QDateTime::currentDateTime().toString("HH:mm:ss"))
                              .arg(newProcessName)
                              .arg(newWindowTitle);
        logInfo(newInfo);
    }
    else
    {
        // 同一窗口活动，更新超时
        updateTimeout();
    }
}

// 更新超时时间
void MainWindow::updateTimeout()
{
    m_lastActivityTime = QDateTime::currentMSecsSinceEpoch();
}

// 检查超时（同一窗口超时仅截图一次）
void MainWindow::checkTimeout()
{
    if (!m_isRunning || !m_lastHWND) return;

    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
    qint64 elapsed = currentTime - m_lastActivityTime;

    if (elapsed > m_timeout)
    {
        // 核心修改：用「窗口句柄+场景标识」作为key，确保同一窗口的超时场景仅截图一次
        QString timeoutKey = QString("%1|timeout").arg((quintptr)m_lastHWND);
        if (m_timeoutScreenshotMap.find(timeoutKey) == m_timeoutScreenshotMap.end()) {
            takeScreenshot("timeout");
            m_timeoutScreenshotMap[timeoutKey] = true;  // 标记该窗口的超时场景已截图
        }

        DWORD processId;
        GetWindowThreadProcessId(m_lastHWND, &processId);
        QString processName = m_processNameMap[processId];
        QString windowTitle = getWindowTitle(m_lastHWND);

        qint64 minutes = elapsed / (1000 * 60);

        QString timeoutInfo = QString("[%1] 超时警告 - 应用名称: %2 | 窗口标题: %3 | 超时时间: %4分钟")
                                  .arg(QDateTime::currentDateTime().toString("HH:mm:ss"))
                                  .arg(processName)
                                  .arg(windowTitle)
                                  .arg(minutes);
        logInfo(timeoutInfo);

        m_lastActivityTime = currentTime;
    }
}

// 截图功能（保存到E:\project_jietu）
void MainWindow::takeScreenshot(const QString &prefix)
{
    if (!m_isRunning) return;

    QScreen *screen = QGuiApplication::primaryScreen();
    if (screen) {
        QPixmap screenshot = screen->grabWindow(0);
        QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss_zzz");
        // 拼接完整保存路径
        QString filename = QString("%1\\%2_%3.png")
                               .arg(SCREENSHOT_ROOT_PATH)
                               .arg(prefix)
                               .arg(timestamp);

        if (screenshot.save(filename)) {
            logInfo(QString("[%1] 截图已保存: %2").arg(
                QDateTime::currentDateTime().toString("HH:mm:ss"),
                filename));
        } else {
            logInfo(QString("[%1] 截图保存失败: %2，请检查路径权限").arg(
                QDateTime::currentDateTime().toString("HH:mm:ss"),
                filename));
        }
    } else {
        logInfo(QString("[%1] 无法获取屏幕设备，截图失败").arg(
            QDateTime::currentDateTime().toString("HH:mm:ss")));
    }
}

// 随机时间截图（间隔10-30分钟）
void MainWindow::takeRandomScreenshot()
{
    takeScreenshot("random");

    // 生成10-30分钟的随机间隔（毫秒）
    m_randomScreenshotInterval = QRandomGenerator::global()->bounded(
        MIN_RANDOM_SCREENSHOT_INTERVAL,
        MAX_RANDOM_SCREENSHOT_INTERVAL + 1  // bounded左闭右开，+1包含最大值
        );
    m_randomScreenshotTimer->start(m_randomScreenshotInterval);

    // 转换为分秒显示
    qint64 nextMin = m_randomScreenshotInterval / 60000;
    qint64 nextSec = (m_randomScreenshotInterval % 60000) / 1000;
    logInfo(QString("[%1] 下次随机截图将在 %2分%3秒 后")
                .arg(QDateTime::currentDateTime().toString("HH:mm:ss"))
                .arg(nextMin).arg(nextSec));
}

// 日志输出
void MainWindow::logInfo(const QString &info)
{
    ui->textEdit->append(info);
    QTextCursor cursor = ui->textEdit->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->textEdit->setTextCursor(cursor);
}

// 开始按钮点击事件
void MainWindow::on_pushButton_start_clicked()
{
    if (m_isRunning) return;

    // 重置所有状态（包括截图记录）
    m_lastHWND = nullptr;
    m_lastActivityTime = QDateTime::currentMSecsSinceEpoch();
    m_processPathMap.clear();
    m_processNameMap.clear();
    m_totalTimeMap.clear();
    m_screenshotRecordMap.clear();  // 清空窗口截图记录（包含场景标识）
    m_timeoutScreenshotMap.clear(); // 清空超时截图记录（包含场景标识）
    m_windowElapsedTimer->invalidate();

    // 检查截图目录是否存在（二次确认）
    QDir screenshotDir(SCREENSHOT_ROOT_PATH);
    if (!screenshotDir.exists()) {
        if (!screenshotDir.mkpath(".")) {
            QMessageBox::critical(this, "错误",
                                  QString("无法创建截图目录: %1，启动失败").arg(SCREENSHOT_ROOT_PATH));
            ui->lineEdit_showOk->setText("启动失败");
            return;
        }
    }

    // 同时设置鼠标钩子和键盘钩子，两者都成功才启动监控
    if (!setMouseHook() || !setKeyboardHook())
    {
        ui->lineEdit_showOk->setText("启动失败");
        return;
    }

    // 启动定时器
    m_timer->start(1000);

    // 启动随机截图（初始间隔10-30分钟）
    m_randomScreenshotInterval = QRandomGenerator::global()->bounded(
        MIN_RANDOM_SCREENSHOT_INTERVAL,
        MAX_RANDOM_SCREENSHOT_INTERVAL + 1
        );
    m_randomScreenshotTimer->start(m_randomScreenshotInterval);
    qint64 nextMin = m_randomScreenshotInterval / 60000;
    qint64 nextSec = (m_randomScreenshotInterval % 60000) / 1000;

    // 更新状态
    m_isRunning = true;
    ui->lineEdit_showOk->setText("正常运行中");
    ui->pushButton_start->setEnabled(false);
    ui->pushButton_end->setEnabled(true);
    logInfo("[系统] 监控已启动，超时时间设置为30分钟");
    logInfo(QString("[系统] 随机截图已启动（间隔10-30分钟），下次截图将在 %1分%2秒 后")
                .arg(nextMin).arg(nextSec));
    logInfo("[系统] 鼠标+键盘钩子已启用，支持两种操作触发窗口切换监控");
}

// 结束按钮点击事件
void MainWindow::on_pushButton_end_clicked()
{
    if (!m_isRunning) return;

    // 停止定时器
    m_timer->stop();
    m_randomScreenshotTimer->stop();

    // 移除钩子（同时移除鼠标和键盘钩子）
    unsetMouseHook();
    unsetKeyboardHook();

    // 输出最后一个窗口的统计信息
    if (m_lastHWND && m_windowElapsedTimer->isValid()) {
        qint64 duration = m_windowElapsedTimer->elapsed();
        m_totalTimeMap[m_lastHWND] += duration;

        DWORD processId;
        GetWindowThreadProcessId(m_lastHWND, &processId);
        QString processName = m_processNameMap[processId];

        qint64 totalSeconds = m_totalTimeMap[m_lastHWND] / 1000;
        qint64 totalMinutes = totalSeconds / 60;
        totalSeconds %= 60;

        logInfo(QString("[系统] 监控结束 - 最后监控的应用: %1 | 总运行时间: %2分%3秒")
                    .arg(processName)
                    .arg(totalMinutes).arg(totalSeconds));
    }

    // 最后截图
    takeScreenshot("monitor_end");

    // 更新状态
    m_isRunning = false;
    ui->lineEdit_showOk->setText("已停止");
    ui->pushButton_start->setEnabled(true);
    ui->pushButton_end->setEnabled(false);
    logInfo("[系统] 监控已停止");
    logInfo("[系统] 鼠标+键盘钩子已解除");
}
